"""UI helpers for drawing overlays and instructions."""

from __future__ import annotations

from functools import lru_cache
from typing import Iterable, Mapping, Sequence, TYPE_CHECKING

import pygame

from config import HUD_COLORS, PLAYER_CONFIG
from tasks import TaskManager

if TYPE_CHECKING:
    from crafting import Recipe


@lru_cache(maxsize=8)
def get_font(size: int) -> pygame.font.Font:
    try:
        return pygame.font.Font("simhei.ttf", size)
    except FileNotFoundError:
        return pygame.font.SysFont("microsoftyahei", size)


def draw_controls(screen: pygame.Surface, instructions: Iterable[str]) -> None:
    font = get_font(28)
    for idx, text in enumerate(instructions):
        surface = font.render(text, True, HUD_COLORS["text"])
        screen.blit(surface, (20, 20 + idx * 32))


def draw_hud(screen: pygame.Surface, state, width: int, height: int) -> None:  # type: ignore[no-untyped-def]
    panel_rect = pygame.Rect(0, height - 80, width, 80)
    pygame.draw.rect(screen, HUD_COLORS["panel"], panel_rect)

    font = get_font(26)
    inventory_text = "  ".join(
        f"{name}:{count}" for name, count in state.inventory.items()
    )
    text_surface = font.render(inventory_text, True, HUD_COLORS["text"])
    screen.blit(text_surface, (20, height - 60))

    phase_names = {"day": "白天", "dusk": "黄昏", "night": "夜晚"}
    phase_surface = font.render(
        f"当前时间段: {phase_names.get(state.day_phase, state.day_phase)}",
        True,
        HUD_COLORS["text"],
    )
    screen.blit(phase_surface, (width - phase_surface.get_width() - 20, height - 60))

    _draw_health(screen, state, (20, height - 35))
    _draw_stamina(screen, state, (220, height - 35), 200, 18)


def _draw_health(screen: pygame.Surface, state, position: tuple[int, int]) -> None:  # type: ignore[no-untyped-def]
    x, y = position
    for idx in range(state.health):
        rect = pygame.Rect(x + idx * 26, y, 20, 20)
        pygame.draw.rect(screen, HUD_COLORS["health"], rect)


def _draw_stamina(screen: pygame.Surface, state, position: tuple[int, int], width: int, height: int) -> None:  # type: ignore[no-untyped-def]
    x, y = position
    pygame.draw.rect(screen, (30, 30, 30), (x, y, width, height))
    ratio = state.stamina / PLAYER_CONFIG.max_stamina if state.stamina else 0
    pygame.draw.rect(screen, HUD_COLORS["stamina"], (x + 2, y + 2, (width - 4) * ratio, height - 4))


def draw_task_panel(screen: pygame.Surface, task_manager: TaskManager, base_y: int = 340) -> None:
    task = task_manager.active_task()
    if not task:
        return
    font_title = get_font(32)
    font_body = get_font(24)
    base_x = 20
    title_surface = font_title.render(task.title, True, HUD_COLORS["text"])
    body_surface = font_body.render(task.description, True, HUD_COLORS["text"])
    screen.blit(title_surface, (base_x, base_y))
    screen.blit(body_surface, (base_x, base_y + 40))


def draw_backpack_overlay(
    screen: pygame.Surface,
    items: Sequence[tuple[str, int]],
    selected_index: int,
    capacity: int | None,
    total: int,
    active_item: str,
    name_mapping: Mapping[str, str],
) -> None:
    width, height = screen.get_size()
    panel_rect = pygame.Rect(width // 2 - 260, height // 2 - 190, 520, 380)
    pygame.draw.rect(screen, (20, 20, 20), panel_rect, border_radius=12)
    pygame.draw.rect(screen, (180, 180, 180), panel_rect, width=2, border_radius=12)

    title_font = get_font(34)
    item_font = get_font(26)
    info_font = get_font(22)

    title_surface = title_font.render("背包", True, HUD_COLORS["text"])
    screen.blit(title_surface, (panel_rect.centerx - title_surface.get_width() // 2, panel_rect.top + 16))

    y = panel_rect.top + 70
    for idx, (name, count) in enumerate(items):
        label = name_mapping.get(name, name)
        selected = idx == selected_index
        active = name == active_item
        prefix = "▶ " if selected else "  "
        suffix = " [放置中]" if active else ""
        color = (255, 215, 0) if selected else HUD_COLORS["text"]
        text_surface = item_font.render(f"{prefix}{label}: {count}{suffix}", True, color)
        screen.blit(text_surface, (panel_rect.left + 32, y))
        y += 32

    if not items:
        empty_surface = item_font.render("背包为空", True, HUD_COLORS["text"])
        screen.blit(empty_surface, (panel_rect.centerx - empty_surface.get_width() // 2, y))

    if capacity is None:
        capacity_text = f"{total}/无限制"
    else:
        capacity_text = f"{total}/{capacity}"
    info_surface = info_font.render(f"容量: {capacity_text}", True, HUD_COLORS["text"])
    screen.blit(info_surface, (panel_rect.left + 32, panel_rect.bottom - 90))

    helper_text = "方向键选择  回车设为放置物  Q丢弃  B/ESC关闭"
    helper_surface = info_font.render(helper_text, True, HUD_COLORS["text"])
    screen.blit(helper_surface, (panel_rect.left + 32, panel_rect.bottom - 50))


def draw_crafting_overlay(
    screen: pygame.Surface,
    recipes: Sequence["Recipe"],
    selected_index: int,
    inventory: Mapping[str, int],
    name_mapping: Mapping[str, str],
) -> None:
    width, height = screen.get_size()
    panel_rect = pygame.Rect(width // 2 - 300, height // 2 - 210, 600, 420)
    pygame.draw.rect(screen, (18, 18, 30), panel_rect, border_radius=12)
    pygame.draw.rect(screen, (120, 120, 200), panel_rect, width=2, border_radius=12)

    title_font = get_font(34)
    body_font = get_font(24)
    helper_font = get_font(22)

    title_surface = title_font.render("合成台", True, HUD_COLORS["text"])
    screen.blit(title_surface, (panel_rect.centerx - title_surface.get_width() // 2, panel_rect.top + 16))

    y = panel_rect.top + 70
    for idx, recipe in enumerate(recipes):
        selected = idx == selected_index
        available = recipe.can_craft(inventory)
        name_color = (144, 238, 144) if available else (170, 170, 170)
        if selected:
            name_color = (255, 215, 0)

        prefix = "▶ " if selected else "  "
        name_surface = body_font.render(f"{prefix}{recipe.name} ({recipe.summary})", True, name_color)
        screen.blit(name_surface, (panel_rect.left + 28, y))
        y += 30

        inputs = " + ".join(
            f"{amount}{name_mapping.get(name, name)}" for name, amount in recipe.inputs.items()
        )
        outputs = " + ".join(
            f"{amount}{name_mapping.get(name, name)}" for name, amount in recipe.outputs.items()
        )
        detail_surface = helper_font.render(f"需要: {inputs}   获得: {outputs}", True, HUD_COLORS["text"])
        screen.blit(detail_surface, (panel_rect.left + 48, y))
        y += 34

    helper_text = "方向键切换配方  回车合成  B/ESC关闭"
    helper_surface = helper_font.render(helper_text, True, HUD_COLORS["text"])
    screen.blit(helper_surface, (panel_rect.left + 28, panel_rect.bottom - 50))
